import { any } from "../../core/logic";
import { ComponentType } from "../Component";
import { Light } from "./Light";
import { color } from "../../core/color";
import { mat4, vec3 } from '../../core/math/wgpu-matrix.module';
import { Engine } from "../../Engine";
import { Matrix4 } from "../../core/math/Matrix4";
import { Quaternion } from "../../core/math/Quaternion";
import { Euler } from "../../core/math/Euler";
import { lookAt, invert, decompose, makeMatrix44 } from "../../core/math/M4"
import { Vector3 } from "../../core/math/V3"
import { Buffer } from "../../gpu/types/Buffer";


/**
 * 点光源。
 * @class
 * @extends w.light.Light
 * @memberof w.light
 */
class PointLight extends Light {
  /**
   * @constructor
   * @param {*} opts.distance 【衰减距离,缺省:0】 0:代表不衰减。
   * @example
   * let light=new w.light.PointLight({distance:100,intensity:1.0,color:"#ffff00"});
   */
  constructor(opts = {}) {
    opts.type = any(opts.type, ComponentType.PointLight);
    super(opts);
    this.lightbuffer = [];
    this.lightType = 1;
    this._distance = any(opts.distance, 0);
    this.cast = any(opts.cast, false);
    this.shadowBias = any(opts.shadowBias, 0.005)
    this.setState(true)
    this.autoUpdate = true;
    this.initShadow()
    this.update();
  }
  /**
   * @property {Number} 光源的衰减距离。
   */
  set distance(v) {
    this._distance = v;
    this.setState(false, "lightBuffer");
    this.update();
    return this;
  }
  get distance() {
    return this._distance;
  }
  get cast() {
    return this._cast;
  }
  get shadowBias() {
    return this._shadowBias;
  }
  /**
   * @property {Number} 阴影上边范围。
   */
  set shadowBias(v) {
    this._shadowBias = v;
    this.setState(false, "lightBuffer");
    this.update();
    return;
  }
  /**
   * @property {Array} 平行光的cast属性。
   */
  set cast(v) {
    this._cast = v;
    if (v) {
      this.initShadow()
    }
    this.setState(false, "lightBuffer");
    this.update();
    return;
  }
  inputShadowData() {
    this.lightViewProj = this.getViewProj();
    let vp = new Float32Array(this.lightViewProj)
    this.shadowBuffer.buffer(vp)
  }
  getViewProj() {
    if (this.cast) {
      const projectCamera = mat4.perspective(90, 1, 1, 200000)
      // //   let  projectCamera= Mat4.create()
      // //    Mat4.perspectiveZO(projectCamera,90,1,0.1,250)
      //   const lightPosition =  vec3.fromValues(...this.trans.position);
      //   const right= vec3.fromValues(1.0,0.0,0.0)   
      //   const left= vec3.fromValues(-1.0,0.0,0.0)   
      //   const up= vec3.fromValues(0.0,1.0,0.0) 
      //   const down= vec3.fromValues(0.0,-1.0,0.0) 
      //   const front= vec3.fromValues(0.0,0.0,1.0) 
      //   const back= vec3.fromValues(0.0,0.0,-1.0) 
      let data = [];
      const scene = Engine.instance.scene;
      const cameraCom = scene.getCamera();
      const far = cameraCom.far
      data.push(...this.trans.position,)
      data.push(far)
      //  //right
      //   const pointRightTarget= vec3.add(lightPosition,[1, 0, 0])
      //   let viewRight= mat4.lookAt(lightPosition,pointRightTarget,[0, -1, 0])
      // //   viewRight= mat4.scale(viewRight,[-1,1,1])
      //   // viewRight=  mat4.rotateX(viewRight,Math.PI/2)
      //   const rightPv= mat4.multiply(projectCamera,viewRight)
      //   data.push(rightPv)
      //  //left
      //   const pointLeftTarget= vec3.add(lightPosition,[-1, 0, 0])
      //   let viewLeft= mat4.lookAt(lightPosition,pointLeftTarget,[0, -1, 0])
      // //   viewRight= mat4.scale(viewLeft,[-1,1,1])
      //   // viewLeft=  mat4.rotateX(viewLeft,Math.PI/2)
      //   const leftPv= mat4.multiply(projectCamera,viewLeft)
      //   data.push(leftPv)
      //  //top
      //   const pointTopTarget= vec3.add(lightPosition,[0, 0, 1])
      //   let viewTop= mat4.lookAt(lightPosition,pointTopTarget,[0, 1,0])
      // //   viewRight=mat4.scale(viewTop,[-1,1,1])
      //   // viewTop=  mat4.rotateX(viewTop,Math.PI/2)
      //   const topPv= mat4.multiply(projectCamera,viewTop)
      //   data.push(topPv)
      //  //botoom
      //   const pointBottomTarget= vec3.add(lightPosition,[0, , -1])
      //   let viewBottom= mat4.lookAt(lightPosition,pointBottomTarget,[0, -1, 0])
      // //   viewBottom=mat4.scale(viewBottom,[-1,1,1])
      //   // viewBottom=  mat4.rotateX(viewBottom,Math.PI/2)
      //   const bottomPv= mat4.multiply(projectCamera,viewBottom)
      //   data.push(bottomPv)
      //  //near
      //   const pointForwardTarget= vec3.add(lightPosition,[0, 0, 1])
      //   let viewForward= mat4.lookAt(lightPosition,pointForwardTarget,[0, -1, 0])
      // //   viewForward=mat4.scale(viewForward,[-1,1,1])
      //   // viewForward=  mat4.rotateX(viewForward,Math.PI/2)
      //   const forwardPv= mat4.multiply(projectCamera,viewForward)
      //   data.push(forwardPv)
      //  //far
      //   const pointBackTarget= vec3.add(lightPosition,[0, 0, -1])
      // //   let  viewBack=Mat4.create()
      // //   Mat4.lookAt(viewBack,lightPosition,pointBackTarget,[0, -1, 0])
      //   let viewBack= mat4.lookAt(lightPosition,pointBackTarget,[0, -1, 0])
      //   // viewBack=mat4.scale(viewBack,[1,-1,1])
      //   // viewBack=  mat4.rotateX(viewBack,Math.PI/2)
      //   let backPv= mat4.multiply(projectCamera,viewBack)
      //   data.push(backPv)
      // const targetDirections = [
      //     [1, 0, 0], // 右侧
      //     [-1, 0, 0], // 左侧
      //     [0, 1, 0], // 上方
      //     [0, -1, 0], // 下方
      //     [0, 0, 1], // 近处（相对于光源）
      //     [0, 0, -1], // 远处
      //   ];

      //   const upDirections = [
      //     [0, -1, 0],
      //     [0, -1, 0],
      //     [0, 0, 1],
      //     [0, 0, -1],
      //     [0, -1, 0],
      //     [0, -1, 0], // 对于近和远，通常沿同一方向
      //   ];

      //   // 创建六个视图矩阵
      //   const viewMatrices = targetDirections.map((target, index) => {
      //     var targetD=[target[0]+lightPosition[0],target[1]+lightPosition[1],target[2]+lightPosition[2]]
      //     var v= mat4.lookAt( lightPosition, targetD, upDirections[index]);
      //     // mat4.scale(v,[-1,1,1])
      //     v=  mat4.rotateX(v,Math.PI)
      //     const pv= mat4.multiply(projectCamera,v)
      //     data.push(pv)
      //   });
      // let gg = mat4.set(-2.220446049250313e-16, 0, 1, 0, 0, 1, 0, -0, 1, 0, 2.220446049250313e-16, 0, -100, -0, -2.220446049250313e-14, 1)
      // let jj = mat4.multiply(projectCamera, gg)
      // console.log(jj, "gg");
      // let viewRight = mat4.lookAt([0, 0, 0], [0, 1, 0], [0, -1, 0])
      // console.log(viewRight, "viewRight");
      // const q = new Quaternion(0, 0.7070714284998106, 0.7071421356408745, 0)
      // const e = new Euler()
      // e.setFromQuaternion(q)
      // console.log(e);
      // let eye = new Vector3(0, 0, 0)
      // let at = new Vector3(0, 1, 0)
      // let up = new Vector3(0, -1, 0)
      // const oo = lookAt(eye, at, up)
      // const invertData = invert(oo)
      // const psq = decompose(invertData, "quaternion")
      // console.log(psq, "psq");
      // right        
      let rotateRight = new Vector3(0, 90, 0)
      let positionRight = new Vector3(...this.trans.position)
      let scaleRight = new Vector3(-1, 1, 1)
      const matRight = makeMatrix44(rotateRight, positionRight, scaleRight)
      const vRight = invert(matRight)
      let right = mat4.multiply(projectCamera, vRight)
      data.push(...right)
      // let r = new Float32Array([2.220446049250313e-16, 0, 1.0000050067901611, 1, 0, 1, 0, 0, -1, 0, 2.220457166557746e-16, 2.220446049250313e-16, 100, 0, -1.0000050067901611, -2.220446049250313e-14])
      // data.push(r)
      // left
      let rotateLeft = new Vector3(0, -90, 0)
      let positionLeft = new Vector3(...this.trans.position)
      let scaleleft = new Vector3(-1, 1, 1)
      const matLeft = makeMatrix44(rotateLeft, positionLeft, scaleleft)
      const vleft = invert(matLeft)
      let left = mat4.multiply(projectCamera, vleft)
      data.push(...left)
      // let l = new Float32Array([2.220446049250313e-16, 0, -1.0000050067901611, -1, 0, 1, 0, 0, 1, 0, 2.220457166557746e-16, 2.220446049250313e-16, -100, 0, -1.0000050067901611, -2.220446049250313e-14])
      // data.push(l)
      // top
      let rotateTop = new Vector3(90, 180, 180)
      let positionTop = new Vector3(...this.trans.position)
      let scaleTop = new Vector3(-1, 1, 1)
      const matTop = makeMatrix44(rotateTop, positionTop, scaleTop)
      const vTop = invert(matTop)
      let Top = mat4.multiply(projectCamera, vTop)
      data.push(...Top)
      // let t = new Float32Array([1, -1.2247692753158257e-16, 1.2245305179038184e-16, 1.22452442985451e-16, -1.2246467202362698e-16, -0.00009999000030802563, 1.0000050067901611, 1, -1.2246468525851679e-16, -1, -0.00009999050234910101, -0.00009999000030802563, 1.224646841997256e-14, 100, -0.9900059700012207, 0.009998999536037445])
      // data.push(t)
      // down
      let rotateDown = new Vector3(-90, 180, 180)
      let positionDown = new Vector3(...this.trans.position)
      let scaleDown = new Vector3(-1, 1, 1)
      const matDown = makeMatrix44(rotateDown, positionDown, scaleDown)
      const vDown = invert(matDown)
      let Down = mat4.multiply(projectCamera, vDown)
      data.push(...Down)
      // let b = new Float32Array([1, 1.22452442985451e-16, -1.224775363365134e-16, -1.2247692753158257e-16, -1.2246468525851679e-16, -0.00009999000030802563, -1.0000050067901611, -1, -1.2246467202362698e-16, 1, -0.00009999050234910101, -0.00009999000030802563, 1.2246467572939613e-14, -100, -0.9900059700012207, 0.009998999536037445])
      // data.push(b)
      // front
      let rotateFront = new Vector3(0, 0, 0)
      let positionFront = new Vector3(...this.trans.position)
      let scaleFront = new Vector3(-1, 1, 1)
      const matFront = makeMatrix44(rotateFront, positionFront, scaleFront)
      const vFront = invert(matFront)
      let Front = mat4.multiply(projectCamera, vFront)
      data.push(...Front)
      // let f = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1.0000050067901611, 1, 0, 0, -101.00050354003906, -100])
      // data.push(f)
      // back
      let rotateBack = new Vector3(180, 0, 180)
      let positionBack = new Vector3(...this.trans.position)
      let scaleBack = new Vector3(-1, 1, 1)
      const matBack = makeMatrix44(rotateBack, positionBack, scaleBack)
      const vBack = invert(matBack)
      let Back = mat4.multiply(projectCamera, vBack)
      data.push(...Back)
      // let back = new Float32Array([-1, 1.2246468525851679e-16, 1.4997673979344746e-32, 1.499759904157988e-32, 1.2246468525851679e-16, 1, 1.2246529406344762e-16, 1.2246468525851679e-16, 1.563254935637622e-39, 1.2246468525851679e-16, -1.0000050067901611, -1, -1.563255608260885e-37, -1.224646841997256e-14, 99.00049591064453, 100])
      // data.push(back)
      return data
    }
  }
  initShadow() {
    if (this.cast) {
      if (!this.shadowBuffer) {
        this.shadowBuffer = new Buffer({
          id: "SingleLightCamera",
          name: "SingleLightCamera",
          usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC,
          visibility: GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT,
          size: 64 * 6 + 4 * 4,
          data: new Float32Array(16 * 6 + 4),
          type: "read-only-storage"
        });
      }
    }
  }
  getLightBuffer() {
    if (!this.getState("lightBuffer")) {
      let _color = color.format(this.color, false);
      this.lightbuffer = [..._color,//0-2
      this.lightType,//3
      ...this.trans.position,//4-6
      this.intensity,//7
        0, 0, 0,//8-10  at
      this.distance,//11
      Number(this.cast),//12
      this.shadowBias,//13
        0,//14 
        0//15
      ];
      this.setState(true, "lightBuffer");
      if (this.cast) {
        this.inputShadowData()
        // this.shadowData = {
        //   position: this.trans.position,
        //   viewProj: lightViewProj
        // }
        this.setState(true, "lightBuffer");
      }
    }
    return this.lightbuffer;
  }
}
export { PointLight }

// let b = new Float32Array(16);
// let c = color.format(this.color, false);
// b.set(c, 0); //颜色
// b.set([this.type], 3); //类型
// b.set(this.position, 4); //位置或方向
// b.set([this.intensity], 7); //强度
// b.set(this.at, 8); //距离
// b.set([this.distance], 11); //innerRad
// b.set([0], 12); //innerRad|width
// b.set([0], 13); //outerRad|height